/**
 * 实现方块
 * 创建者：Carburn Ashroom
 * 2023.11.14
 */

class Block {       // Block类是一个俄罗斯方块
    
    constructor(type, pos =blkInitPos, mov =blkInitMove, speed =blkSpeed, hSpeed =blkQSpeed, shapeIndex =0) {
        this.typeIndex = blkNames.indexOf(type);
        this.shapeIndex = shapeIndex;
        this.pos = pos;
        this.move = mov;
        this.goalMove = mov;
        this.speed = speed;
        this.lSpeed = speed;
        this.hSpeed = hSpeed;
        this.blocks = this.getBlocks();
        this.absltBlocks = this.getAbsltBlocks();
        this.color = blkColors[this.typeIndex];
    }
    
    draw(context) {     // 绘制
        context.fillStyle = this.color;
        for (let i of this.blocks) {
            context.fillRect(this.move+i[0]*blkSize, this.pos+i[1]*blkSize, blkSize, blkSize);
        }
    }
    
    getAbsltBlocks() {      // 获取当前所有方块的位置
        let offX = Math.floor(this.goalMove/blkSize);
        let offY = Math.floor(this.pos/blkSize) + 1;
        let blkList = [];
        for (let b of this.blocks) {
            blkList.push([b[0]+offX, b[1]+offY]);
        }
        return blkList;
    }

    getBlocks() {       // 获取所有方块的初始位置
        let style = [[0, 0]];
        for (let s of blkStyle[this.typeIndex][this.shapeIndex]) {
            style.push(s);
        }
        return style;
    }

    update() {      // 更新每一帧的状态
        this.pos += this.speed;
        if (Math.abs(this.move-this.goalMove) <= this.hSpeed) {
            this.move = this.goalMove;
        }
        else {
            this.move += this.hSpeed * ((this.move<this.goalMove) ? 1 : -1);
        }
        this.absltBlocks = this.getAbsltBlocks();
    }
    
    moveTo(offset) {        // 向右移动指定位移，负数则向左移动
        if (this.goalMove == this.move) {
            this.goalMove += offset * blkSize;
        }
    }

    movePosTo(x, y) {       // 立刻移动到坐标位置
        this.move = x;
        this.goalMove = x;
        this.pos = y;
    }

    copy() {        // 深拷贝一个对象并返回
        let newBlock = new Block("T");
        for (let p in this) {
            newBlock[p] = this[p];
        }
        newBlock.absltBlocks = newBlock.getAbsltBlocks();
        newBlock.blocks = newBlock.getBlocks();
        return newBlock;
    }
    
    rotate(offset) {        // 顺时针旋转offset次，若为负值则逆时针。offset必须小于其旋转一周的次数
        this.shapeIndex += offset;
        if (this.shapeIndex >= blkStyle[this.typeIndex].length) {
            this.shapeIndex -= blkStyle[this.typeIndex].length;
        }
        else if (this.shapeIndex < 0) {
            this.shapeIndex += blkStyle[this.typeIndex].length;
        }
        this.blocks = this.getBlocks();
        this.absltBlocks = this.getAbsltBlocks();
    }

    quicker() { this.speed = this.hSpeed; }

    lower() { this.speed = this.lSpeed; }

}
        
class Square {      // Square类提供了已经提交在画布上的方块

    constructor(x, y, valid =false, color =null, speed =blkQSpeed, delFrame =blkDelFrame) {
        this.posX = x * blkSize;
        this.posY = y * blkSize;
        this.goalPos = this.posY;
        this.valid = valid;
        this.color = color;
        this.delFrame = -1;
        this.speed = speed;
        this.delTime = delFrame;
    }

    draw(context) {     // 绘制
        context.fillStyle = this.color;
        context.fillRect(this.posX, this.posY, blkSize, blkSize);
        if (this.delFrame >= 0) {
            let tColor = "rgba(" + backColor[0] + "," + backColor[1] + "," + backColor[2] + "," + (this.delTime-this.delFrame)/this.delTime + ")";
            context.fillStyle = tColor; 
            context.fillRect(this.posX, this.posY, blkSize, blkSize);
        }
    }

    del() { this.delFrame = this.delTime; }

    update() {      // 更新状态，返回是否不在移动状态（移动完毕或未移动）
        if (this.goalPos > this.posY) {
            this.posY += this.speed;
            return false;
        }
        else if (this.goalPos < this.posY) {
            this.posY = this.goalPos;
        }
        if (this.delFrame == 0) {
            this.valid = false;
        }
        else if (this.delFrame > 0) {
            --this.delFrame;
        }
        return true;
    }

    drop(distance) { this.goalPos += distance * blkSize; }

    getPos() { return [Math.floor(this.posX/blkSize), Math.floor(this.posY/blkSize)]; }

    moving() { return this.posY != this.goalPos; }
    
}
